<?php
/**
 * FlickrPhotosetsCanvas class file
 * @package FlickrPhotosets
 */

/**
 * This class is responsible for displaying canvas pages.
 * 
 * It should be used to control all canvas pages unless something special
 * is required for that page.
 * 
 * @package FlickrPhotosets
 * @author Brad Dougherty <bdougherty@gmail.com>
 * @version 8.5.28
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License 3.0
 */
class FlickrPhotosetsCanvas extends FlickrPhotosets {
	
	/**
	 * FBML to print at the end of the page
	 * @var string
	 */
	public $closing_fbml;
	
	/**
	 * FBML to print at the beginning of the page
	 * @var string
	 */
	public $opening_fbml;
	
	// For getting the uid
	const require_login = 'login';
	const uid_from_url = 'url';
	const uid_from_viewer = 'viewer';
	
	/**
	 * Requires that the page is rendered in the frame. Get's the UID by either
	 * using the url, requiring login, requiring add, or from the viewer. It
	 * will also set up the Flickr object. $check_preferences should be set to
	 * false if the page is a "backend" page.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @param string $where_uid Where to get the UID from (use static variables in FlickrPhotosets)
	 * @param boolean $initialize_flickr Initialize Flickr
	 * @param boolean $check_preferences Check that preferences are honored
	 */
	public function __construct($where_uid = 'url', $initialize_flickr = true, $check_preferences = true, $get_info = true) {
		parent::__construct();
		
		// To make this a canvas page, we should require the frame
		$this->facebook->require_frame();
		
		// Get the UID
		if ($where_uid == self::require_login) {
			$this->uid = $this->facebook->require_login();
		}
		else if ($where_uid == self::uid_from_viewer) {
			$this->uid = ($this->facebook->get_canvas_user()) ? $this->facebook->get_canvas_user() : $this->facebook->get_loggedin_user();
			if ($this->facebook->get_canvas_user())
				return false;
		}
		else {
			$this->uid = (!empty($_GET['uid'])) ? $_GET['uid'] : $_GET['id']; // Get the id for backwards compatibility
		}
		
		// Figure out the UID if the username is passed in
		if (!is_numeric($this->uid)) {
			$flickr = new phpFlickr(FLICKR_API_KEY, FLICKR_API_SECRET);
			$nsid = $flickr->urls_lookupUser('http://flickr.com/photos/'.$this->uid);
			$this->uid = $this->get_uid_from_nsid($nsid['id']);
		}
		
		// Now that we have the UID, let's get their configuration data
		if ($get_info and !$this->get_info()) {
			$this->error(FlickrPhotosetsErrors::$not_added);
		}

		// Migrate to new flickr api key
		$this->_migrate_flickr_key();
				
		// Check the preferences for things that are disabled
		if ($check_preferences) {
			$this->check_preferences();
		}
		
		// Set up Flickr
		if ($initialize_flickr) {
			$this->init_flickr();
			
			// Retrieve the page number
			$this->get_page();
		}
		
		// Echo any opening fbml
		echo $this->opening_fbml;
	}
	
	/**
	 * Adds code to the opening and closing FBML to be printed before and after
	 * the content of the page. Must be called before the end of the constructor.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @param string $opening_fbml The code to add to the opening FBML
	 * @param string $closing_fbml The code to add to the closing FBML
	 */
	private function add_to_fbml($opening_fbml, $closing_fbml) {
		$this->opening_fbml = $opening_fbml.$this->opening_fbml;
		$this->closing_fbml = $this->closing_fbml.$closing_fbml;
	}
	
	/**
	 * Enforces the user's preferences.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 */
	private function check_preferences($first = true) {
		
		// If the user has disabled the gallery
		if (!$this->has_enabled_gallery()) {
			
			// Try to redirect to the page on Flickr
			if (!empty($_GET['pid']) and !empty($_GET['sid'])) {
				$this->facebook->redirect('http://flickr.com/photos/'.$this->config['flickr_nsid'].'/'.$_GET['pid'].'/in/set-'.$_GET['sid'].'/');
			}
			else if (!empty($_GET['pid'])) {
				$this->facebook->redirect('http://flickr.com/photos/'.$this->config['flickr_nsid'].'/'.$_GET['pid'].'/');
			}
			else if (!empty($_GET['sid'])) {
				$this->facebook->redirect('http://flickr.com/photos/'.$this->config['flickr_nsid'].'/sets/'.$_GET['sid'].'/');
			}
			
			// Otherwise show an error
			$this->error(FlickrPhotosetsErrors::$gallery_disabled);
			
		}
		
		// If the user wants the page only visible to friends
		if ($this->config['privacy_visibility'] == $this->privacy_visibility['friends']) {
			$this->add_to_fbml(
				'<fb:if-is-friends-with-viewer uid="'.$this->uid.'">',
				'<fb:else>'.$this->error(FlickrPhotosetsErrors::$not_friends, true).'</fb:else></fb:if-is-friends-with-viewer>'
			);
		}
		
		// If the user wants to block limited profile friends
		if ($this->config['privacy_visibility'] == $this->privacy_visibility['non-limited']) {
			$this->add_to_fbml(
				'<fb:if-can-see uid="'.$this->uid.'" what="not_limited">',
				'<fb:else>'.$this->error(FlickrPhotosetsErrors::$private, true).'</fb:else></fb:if-can-see>'
			);
		}
		
	}
	
	/**
	 * Prints out the footer, which consists of the closing fbml,
	 * the disclaimer, and google analytics.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @param boolean $border Whether or not to render a border
	 */
	public function echo_footer($border = false) {
		echo $this->closing_fbml;
		echo $this->get_disclaimer($border);
		echo $this->get_analytics();
	}
	
	/**
	 * Prints out a question/answer block.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @param string $question The question
	 * @param string $answer The answer
	 */
	public function echo_help_item($question, $answer) {
		static $help_id = 1;
		echo '
			<div class="question">
				<a href="#" clicktotoggle="ans_'.$help_id.'"><fb:intl>'.$question.'</fb:intl></a>
			</div>
			<div class="answer" id="ans_'.$help_id.'" class="answer" style="display:none;">
				'.$answer.'
			</div>
		';
		$help_id++;
	}
	
	/**
	 * Attempts to match Flickr contacts to Facebook friends.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @return array An array of the UIDs of Facebook friends that are potential matches
	 */
	public function find_friends_on_flickr($loose = false) {
		
		// Get the Flickr contacts and Facebook friends
		$this->flickr->setToken($this->config['flickr_token']);
		$flickr_contacts = $this->flickr->contacts_getList();
		$facebook_friend_uids = $this->facebook->api_client->friends_get();

		// Get the name of your Flickr contacts
		$flickr_friend_names = array();
		foreach ($flickr_contacts['contact'] as $friend) {
			if (!empty($friend['realname'])) {
				array_push($flickr_friend_names, $friend['realname']);
			}
		}

		// Get the names of your Facebook friends
		$facebook_friend_names = $this->facebook->api_client->users_getInfo($facebook_friend_uids, array('name', 'first_name', 'last_name'));
		for ($i = 0; $i < count($facebook_friend_names); $i++) {
			$facebook_friend_names[$i]['name_lower'] = strtolower($facebook_friend_names[$i]['name']);
			$facebook_friend_names[$i]['first_name_lower'] = strtolower($facebook_friend_names[$i]['first_name']);
			$facebook_friend_names[$i]['last_name_lower'] = strtolower($facebook_friend_names[$i]['last_name']);
		}

		/*
		Do our best to match the names.
		If there is a match, push the UID to an array.
		*/
		$friends_on_flickr = array();
		if ($loose) {
			
			/*
			Loop through each friend. If their first or last name is empty, skip.
			Otherwise try to match the last name and first initial or the first name
			and last initial.
			*/
			foreach ($flickr_friend_names as $friend) {

				$first_name = strtolower(substr($friend, 0, strpos($friend, ' ')));
				$last_name = strtolower(substr($friend, strpos($friend, ' ')));

				if (strlen(trim($last_name)) == 0 or strlen(trim($first_name)) == 0) {
					continue;
				}
				else if (strlen(trim($last_name)) > 1 or strlen(trim($first_name)) > 1) {

					// Match Last Name, First Initial
					$friend_key = Utilities::multiArraySearch(trim($last_name), $facebook_friend_names);
					if (!empty($friend_key)) {
						$first_initial = strtolower(substr($friend, 0, 1));
						$first_initial_fb = substr($facebook_friend_names[$friend_key[0]]['first_name_lower'], 0, 1);
						if ($first_initial == $first_initial_fb) {
							array_push($friends_on_flickr, $facebook_friend_names[$friend_key[0]]['uid']);
							continue;
						}
					}

					// Match First Name, Last Initial
					$friend_key = Utilities::multiArraySearch(trim($first_name), $facebook_friend_names);
					if (!empty($friend_key)) {
						$last_initial = strtolower(substr($friend, strpos($friend, ' ')+1, 1));
						$last_initial_fb = substr($facebook_friend_names[$friend_key[0]]['last_name_lower'], 0, 1);
						if ($last_initial == $last_initial_fb) {
							array_push($friends_on_flickr, $facebook_friend_names[$friend_key[0]]['uid']);
							continue;
						}
					}

				}
				else {

					// Match Full Name
					$friend_key = Utilities::multiArraySearch($friend, $facebook_friend_names);
					if (!empty($friend_key)) {
						array_push($friends_on_flickr, $facebook_friend_names[$friend_key[0]]['uid']);
						continue;
					}

				}

			}

		}
		else {
			
			/*
			Loop through each friend. If the first or last name is blank, skip.
			If the last name is 1 and the first name is more than 1, match first name, last initial.
			If the last name is more than 1 and the first name is 1, match last name, first initial.
			Otherwise, match full name.
			*/
			foreach ($flickr_friend_names as $friend) {

				$first_name = trim(strtolower(substr($friend, 0, strpos($friend, ' '))));
				$last_name = trim(strtolower(substr($friend, strpos($friend, ' '))));

				if (strlen(trim($last_name)) == 0 or strlen(trim($first_name)) == 0) {
					// Nothing for first or last name, skipping
					continue;
				}
				else if (strlen($last_name) == 1 and strlen($first_name) > 1) {

					// Match First Name, Last Initial
					$friend_key = Utilities::multiArraySearch(trim($first_name), $facebook_friend_names);
					if (!empty($friend_key)) {
						$last_initial = strtolower(substr($friend, strpos($friend, ' ')+1, 1));
						$last_initial_fb = substr($facebook_friend_names[$friend_key[0]]['last_name_lower'], 0, 1);
						if ($last_initial == $last_initial_fb) {
							array_push($friends_on_flickr, $facebook_friend_names[$friend_key[0]]['uid']);
							continue;
						}
					}

				}
				else if (strlen($last_name) > 1 and strlen($first_name) == 1) {

					// Match Last Name, First Initial
					$friend_key = Utilities::multiArraySearch(trim($last_name), $facebook_friend_names);
					if (!empty($friend_key)) {
						$first_initial = strtolower(substr($friend, 0, 1));
						$first_initial_fb = substr($facebook_friend_names[$friend_key[0]]['first_name_lower'], 0, 1);
						if ($first_initial == $first_initial_fb) {
							array_push($friends_on_flickr, $facebook_friend_names[$friend_key[0]]['uid']);
							continue;
						}
					}

				}
				else {

					// Match Full Name
					$friend_key = Utilities::multiArraySearch($friend, $facebook_friend_names);
					if (!empty($friend_key)) {
						array_push($friends_on_flickr, $facebook_friend_names[$friend_key[0]]['uid']);
						continue;
					}

				}

			}

		}
		
		return $friends_on_flickr;
		
	}
	
	/**
	 * Gets the disclaimer paragraph.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @param boolean $border Add the top border and background color, defaults to false
	 * @return string The disclaimer
	 */
	final public function get_disclaimer($border = false) {
		$disclaimer = '<div id="disclaimer" class="clearfix';
		$disclaimer .= ($border) ? ' with_border">' : '">';
 		$disclaimer .= '<p>This product is not created or endorsed by <a href="http://facebook.com">Facebook</a>. This product uses the <a href="http://flickr.com/services/api/">Flickr API</a> but is not endorsed or certified by <a href="http://flickr.com">Flickr</a>. Hosting provided by <a href="http://www.1and1.com/?k_id=6902840">1&1</a>. '.$this->application_name.' is an <a href="'.$this->canvas_url.'/open-source/">Open Source</a> project.</p></div>';
		return $disclaimer;
	}
	
	/**
	 * Gets a comma-delimited list of friends who are not on Flickr.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @return string A comma-delimited list of friends not on Flickr
	 */
	public function get_friends_not_on_flickr($loose = false) {
		
		// Get the list of friends on flickr and all friends
		$friends_on_flickr = $this->find_friends_on_flickr($loose);
		$facebook_friend_names = $this->facebook->api_client->users_getInfo($this->facebook->api_client->friends_get(), array('has_added_app'));
		$friends_not_on_flickr = '';
		
		/*
		Loop through each friend. If the user isn't in the list of Flickr friends,
		add them to the list.
		*/
		foreach ($facebook_friend_names as $friend) {
			$search = array_search($friend['uid'], $friends_on_flickr);
			if ($search === false) {
				if ($friends_not_on_flickr != '') {
					$friends_not_on_flickr .= ',';
				}
				$friends_not_on_flickr .= $friend['uid'];
			}
		}
		return $friends_not_on_flickr;
	}
	
	/**
	 * Gets a comma-delimited list of friends that have the app installed.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @return string A comma-delimited list of friends with the app installed
	 */
	public function get_friends_with_app() {
		// Get list of friends who have this app installed
		$fql_result = $this->facebook->api_client->fql_query("SELECT uid FROM user WHERE has_added_app=1 and uid IN (SELECT uid2 FROM friend WHERE uid1 = $this->uid)");
		
		// Build a delimited list of friends with the app installed
		$friends_with_app = '';
		for ($i = 0; $i < count($fql_result); $i++) {
			if ($friends_with_app != "") {
				$friends_with_app .= ",";
			}
			$friends_with_app .= $fql_result[$i]["uid"];
		}
		return $friends_with_app;
	}
	
	/**
	 * Gets the new header.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @param string $page_name Page name for the tab
	 * @param string $title Additional text to add to the title
	 * @return string The dashboard header
	 */
	public function get_header($page_name = '', $title = '', $override_title = false) {
		$buddyicon = ($this->is_flickr_authorized()) ?  'http://farm'.$this->flickr_user['iconfarm'].'.static.flickr.com/'.$this->flickr_user['iconserver'].'/buddyicons/'.$this->nsid.'.jpg' : 'http://www.flickr.com/images/buddyicon.jpg';
		
		$header = '<div id="fp_header"><a href="'.$this->canvas_url.'/" title="Home"><img src="'.$buddyicon.'" /></a>';
		$header .= '<h2><a href="'.$this->canvas_url.'/" title="Home"><img src="'.$this->app_properties['icon_url'].'" /></a>';
		if ($override_title) {
			$header .= $title;
		}
		else {
			$header .= ($override_title) ? '' : $this->get_name_fbml(true).' <span style="color: #3e79c0;">Flick</span><span style="color: #d760a9;">r</span> Photos ';
			$header .= (empty($title)) ? '' : ' - '.$title;
		}
		$header .= '</h2>';
		
		$header .= '<div class="links">';
		
		if (in_array($this->viewer_uid, explode(',', $this->get_app_developers()))) {
			$header .= '<a href="'.$this->canvas_url.'/admin/lookup/">Admin</a><span class="pipe"> | </span>';
		}
		
		if ($this->viewer_uid == $this->uid) {
			$header .= '<a href="'.$this->canvas_url.'/configure/">Configure</a><span class="pipe"> | </span>';
		}
		
		$header .= '<a href="'.$this->canvas_url.'/help/">Help</a></div>';
		
		$header .= '<div class="headertabs"><div class="tabwrapper"><div class="thetabs">';
		if (false) {//$page_name == 'home') {
			$header .= '
			<a class="selected" href="'.$this->canvas_url.'/">
				<fb:intl desc="Name of tab for the home page">Home</fb:intl>
			</a>
			';
		}
		if ($this->config['enable_gallery_photostream']) {
			$link = $this->canvas_url.'/photos/'.$this->uid.'/';
			$selected = (strtolower($page_name) == 'photostream') ? 'selected' : '';
			$header .= '
			<a class="'.$selected.'" href="'.$link.'">
				<fb:intl desc="Name of tab for photostream">Photostream</fb:intl>
			</a>
			';
		}
		if ($this->config['enable_gallery_photosets']) {
			$link = $this->canvas_url.'/photos/'.$this->uid.'/sets/';
			$selected = (strtolower($page_name) == 'photosets') ? 'selected' : '';
			$header .= '
			<a class="'.$selected.'" href="'.$link.'">
				<fb:intl desc="Name of tab for photosets">Photosets</fb:intl>
			</a>
			';
		}
		if ($this->config['enable_gallery_geotagged']) {
			$link = $this->canvas_url.'/photos/'.$this->uid.'/geo/';
			$selected = (strtolower($page_name) == 'geotagged') ? 'selected' : '';
			$header .= '
			<a class="'.$selected.'" href="'.$link.'">
				<fb:intl desc="Name of tab for geotagged photos">Geotagged</fb:intl>
			</a>
			';
		}
		if ($this->config['enable_tagging']) {
			$link = $this->canvas_url.'/photos/'.$this->uid.'/tagged/';
			$selected = (strtolower($page_name) == 'tagged') ? 'selected' : '';
			$header .= '
			<a class="'.$selected.'" href="'.$link.'">
				<fb:intl desc="Name of tab for tagged photos of friends">Tagged</fb:intl>
			</a>
			';
		}
		
		if ($this->facebook->get_canvas_user() and $page_name != 'home')
			$header .= '<a href="'.$this->canvas_url.'/">Add '.$this->application_name.'</a>';
		
		$header .= '<a class="selected" href="" style="visibility: hidden;">Dummy</a>';
		$header .= '</div></div></div></div>';
		
		return $header;
	}
	
	/**
	 * Gets the code for the stylesheet.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @return string The code to insert the stylesheet
	 */
	public function get_stylesheet($page = '') {
		if (USE_STYLESHEET_INCLUDE) {
			include('/homepages/12/d120288663/htdocs/apps/flickrphotosets/styles.php');
			return '';
		}
		else {
			return '<link rel="stylesheet" type="text/css" media="screen" href="'.$this->callback_url.'/styles.php?v='.trim(REVISION).'&amp;p='.$page.'" />';
		}
	}
	
	/**
	 * Checks to see if the user is friends with the viewer of the page.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @return boolean True if they are friends
	 * @deprecated Use add_to_fbml() to add the proper FBML tags instead of this method.
	 */
	public function is_friends_with_viewer() {
		// Get the viewer
		$viewer = $this->facebook->get_loggedin_user();
		
		// Only check if the viewer and user are different
		$are_friends = true;
		if ($viewer != $this->uid) {
			$are_friends = $this->facebook->api_client->friends_areFriends($this->uid, $viewer);
			$are_friends = $are_friends[0]['are_friends'];
		}
		
		return ($are_friends) ? true : false;
	}
	
	/**
	 * Prints out the comments for a photo or photoset. Attempts
	 * to match a Flickr user to their Facebook user.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @param array $comments The array returned by any of the _comments_getList functions
	 */
	public function print_comments($comments) {
		
		// Get the count
		$comment_count = count($comments['comment']);
		
		echo '<div class="wallkit_frame"><h3 class="wallkit_title">Flickr Comments</h3><div class="wallkit_subtitle clearfix"><div style="float:left;">';
		
		// If there are comments
		if ($comment_count > 0) {
			
			echo ($comment_count == 1) ? 'Displaying the only comment.' : 'Displaying '.$comment_count.' comments.';
			echo '</div><div style="float:right;">&nbsp;</div></div>';
			
			// TODO: PUT CODE FOR ADDING FLICKR COMMENTS
			
			// Loop through and print each comment
			foreach ($comments['comment'] as $comment) {
				
				// See if the commenter is on Facebook
				$comment_uid = $this->get_uid_from_nsid($comment['author']);
				$commenter_facebook = '';
				if (!empty($comment_uid)) {
					$commenter_facebook = ' (<fb:name uid="'.$comment_uid.'" capitalize="true" />)';
				}
				
				echo '<div class="wallkit_post" id="comment', $comment['permalink'], '"><div class="wallkit_profilepic">',
					'<a href="', $this->flickr->urls_getUserPhotos($comment['author']), '">',
					'<img src="http://flickr.com/buddyicons/', $comment['author'], '.jpg" alt="', $comment['authorname'], '" class="">',
					'</a></div><div class="wallkit_postcontent">',
					'<h4><a href="', $this->flickr->urls_getUserPhotos($comment['author']), '">',
					$comment['authorname'].'</a>', $commenter_facebook, ' says ',
					'<span>on ', date('M j, Y', $comment['datecreate']), '</span></h4><div>', $comment['_content'], 
					'</div><div class="wallkit_actionset"><a href="', $comment['permalink'], '">permalink</a>',
					'<!--<fb:if-is-user uid="', $this->uid, '"> - <a href="', $this->canvas_url, '/', $comment['id'], '">delete</a></fb:if-is-user>--></div></div></div>';
				
			}
			
		}
		// If there are no comments
		else {
			echo 'There are no comments.</div><div style="float:right;">&nbsp;</div></div>';
		}
		
		echo '</div>';
		
		// Make sure we get the styles imported
		$this->add_to_fbml('', '<fb:wall></fb:wall>');
		
	}
	
	/**
	 * Prints out the media header common to canvas pages that display photos.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @param string $extra_text The extra text to put after _'s Flickr Photos
	 */
	public function print_media_header($extra_text = '') {
		echo '
			<div class="media_header clearfix">
				<div class="picture">
					<img src="http://flickr.com/buddyicons/'.$this->nsid.'.jpg" />
				</div>
				<div class="user_info">
					<div class="media_gray_bg clearfix">
						<h2>'.$this->get_name_fbml(true).' 
							<span style="color:#3e79c0;">Flick<span style="color:#d760a9;">r</span></span> Photos';
		echo (empty($extra_text)) ? '' : '<span> - '.$extra_text.'</span>';
		echo '
						</h2>
					</div>
					<div class="media_actions clearfix">
						
						<fb:if-is-user uid="'.$this->uid.'">
							
							<a href="'.$this->canvas_url.'/configure/">Configure</a>
							<span class="pipe">|</span>
							
						<fb:else>
							
							<fb:if-can-see uid="'.$this->uid.'" what="profile">
								<a href="http://facebook.com/profile.php?id='.$this->uid.'">Back to Profile</a>
								<span class="pipe">|</span>
							</fb:if-can-see>
							
						</fb:else></fb:if-is-user>
						
						<a href="'.$this->flickr->urls_getUserProfile($this->nsid).'">'.$this->get_name_fbml().' Flickr Profile</a>

						<span class="pipe">|</span>

						<a href="'.$this->flickr->urls_getUserPhotos($this->nsid).'">'.$this->get_name_fbml().' Flickr Photostream</a>

						<fb:user uid="'.$this->uid.'">
							<fb:else>
								<span class="pipe">|</span>
								<a href="http://facebook.com/inbox/?compose&amp;id='.$this->uid.'">Send <fb:pronoun uid="'.$this->uid.'" objective="true" /> a Message</a>
							</fb:else>
						</fb:user>

					</div>
				</div>
			</div>
			
			<div style="margin-top:20px;"> </div>
		';
	}
	
}

?>